package game;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;

import exceptions.ImpossibleMoveException;
import exceptions.SuicideMoveException;


public class GoGroup {
	
	private int id;
	private int color;
	private LinkedList<Integer> stones_positions;
	private Set<Integer> liberties;
	GoGame game;
	
	public GoGroup(int color, int position, GoGame game) throws ImpossibleMoveException{
		/*
		 * Create a group with one stone
		 */
		this.id = game.getNewGroupId();
		this.color = color;
		this.stones_positions = new LinkedList<Integer>();
		this.stones_positions.add(position);
		this.game = game;
		
		GoBoard board = game.getBoard();
		LinkedList<Integer> neighbours = board.neighbours(position);
		
		
		this.liberties = new HashSet<Integer>();
		
		for (int pos : neighbours) {
			if (board.isFree(pos))  liberties.add(pos);
		}
	}
	
	
	public GoGroup (GoGroup a, GoGame game) {
		this.id = a.getId();
		this.color = a.getColor();
		
		this.stones_positions = new LinkedList<Integer>();
		this.stones_positions.addAll(a.getStonesPositions());
		this.liberties = new HashSet<Integer>();
		this.liberties.addAll(a.getLiberties());
		this.game = game;
	}
	
	public int getId() {
		return id;
	}
	
	public int getColor() {
		return color;
	}
	
	public int getSize() {
		return stones_positions.size();
	}
	
	public LinkedList<Integer> getStonesPositions() {
		return stones_positions;
	}
	
	public Set<Integer> getLiberties() {
		return liberties;
	}
	
	public int getLibertiesCount() {
		return liberties.size();
	}
	
	public void addStone(int position) throws ImpossibleMoveException, SuicideMoveException {
		GoBoard board = game.getBoard();
		LinkedList<Integer> neighbours = board.neighbours(position);
		
		liberties.remove(position);
		
		for (int l : neighbours) {
			if (board.isFree(l)) liberties.add(l);
		}
		stones_positions.add(position);
	}
	
	public void addLiberty(int position) {
		liberties.add(position);
	}
	
	public void deleteLiberty(int position) {
		liberties.remove(position);
	}
	
	static public GoGroup merge(GoGroup a, GoGroup b, GoGame game) {
		
		if (a.getId() == b.getId()) return a;
		
		if (a.getId() > b.getId()) return merge(b,a, game);
		
		try {
			LinkedList<Integer> stones_of_b = b.getStonesPositions();
			
			GoGroup res = new GoGroup(a,game);
			for (int s : stones_of_b) res.addStone(s);
			return res;
		} catch (Exception e) {
			System.err.println("Internal error");
			e.printStackTrace();
			return null;
		} 
	}
	
	public String toString() {
		String s = "Group "+id+" : color="+color+", stones=[";
		for (int stone : stones_positions) {
			s += game.getBoard().labelPosition(stone)+",";
		}
		s += "], liberties=[";
		for (int lib:liberties) {
			s += game.getBoard().labelPosition(lib)+",";
		}
		s += "]";
		
		return s;
	}
}
